=begin pod :tag<perl6>

=TITLE Object Orientation

=SUBTITLE Object Orientation in Perl 6

Perl 6 provides strong support for object oriented programming. Although
Perl 6 allows programmers to program in multiple paradigms, object oriented
programming is at the heart of the language.

Perl 6 comes with a wealth of predefined types, which can be classified in
two categories: normal and I<native> types.

Native types are used for low-level types (like C<uint64>). They do not have
the same capabilities as objects, though if you call methods on them, they
are I<boxed> into normal objects.

Everything that you can store in a variable is either a native value or an
object. That includes literals, types (type objects), code and containers.

=head1 Using Objects

To call a method on an object, add a dot, followed by the method name:

=for code
say "abc".uc;
# OUTPUT: «ABC␤»

This calls the C<uc> method on C<"abc">, which is an object of type
C<Str>. To supply arguments to the method, add arguments inside parentheses
after the method.

=for code
my $formatted-text = "Fourscore and seven years ago...".indent(8);
say $formatted-text;
# OUTPUT: «        Fourscore and seven years ago...␤»

C<$formatted-text> now contains the above text, but indented 8 spaces.

Multiple arguments are separated by commas:

=for code :preamble<my $formatted-text;>
my @words = "Abe", "Lincoln";
@words.push("said", $formatted-text.comb(/\w+/));
say @words;
# OUTPUT: «[Abe Lincoln said (Fourscore and seven years ago)]␤»

Multiple arguments can be specified by separating the argument list with a colon:

=for code :preamble<my @words;>
say @words.join: '--';
# OUTPUT: «Abe--Lincoln--said--Fourscore--and--seven--years--ago␤»

Since you have to put a C<:> after the method if you want to pass arguments
without parentheses, a method call without a colon or parentheses is
unambiguously a method call without an argument list:

    say 4.log:   ; # OUTPUT: «1.38629436111989␤» ( natural logarithm of 4 )
    say 4.log: +2; # OUTPUT: «2␤» ( base-2 logarithm of 4 )
    say 4.log  +2; # OUTPUT: «3.38629436111989␤» ( natural logarithm of 4, plus 2 )

Many operations that don't look like method calls (for example, smart
matching, or interpolating an object into a string) result in method calls
under the hood.

Methods can return mutable containers, in which case you can assign to the
return value of a method call. This is how read-writable attributes to
objects are used:

=for code
$*IN.nl-in = "\r\n";

Here, we call method C<nl-in> on the C<$*IN> object, without arguments,
and assign to the container it returned with the L<C<=>|=> operator.

All objects support methods from class L<Mu>, which is the type hierarchy root.
All objects derive from C<Mu>.

=head2 Type Objects

Types themselves are objects and you can get the I<type object> by writing its name:

=for code
my $int-type-obj = Int;

You can ask any object for its type object by calling the C<WHAT> method
(which is actually a macro in method form):

=for code :ok-test<WHAT>
my $int-type-obj = 1.WHAT;

Type objects (other than L<Mu>) can be compared for equality with the
L<C<===>|===> identity operator:

=for code :ok-test<WHAT>
sub f(Int $x) {
    if $x.WHAT === Int {
        say 'you passed an Int';
    }
    else {
        say 'you passed a subtype of Int';
    }
}

Although, in most cases, the L<C<.isa>|isa> method will suffice:

=for code
sub f($x) {
    if $x.isa(Int) {
        ...
    }
    ...
}

Subtype checking is done by L<smart-matching|/language/operators#infix_~~>:

=for code :preamble<my $type;>
if $type ~~ Real {
    say '$type contains Real or a subtype thereof';
}

=head1 X<Classes|declarator,class>

Classes are declared using the C<class> keyword, typically followed by a
name.

    class Journey { }

This declaration results in a type object being created and installed in the
current package and current lexical scope under the name C<Journey>.  You
can also declare classes lexically:

    my class Journey { }

This restricts their visibility to the current lexical scope, which can be
useful if the class is an implementation detail nested inside a module or
another class.

=head2 Attributes
X<|Attribute> X<|Property> X<|Member> X<|Slot>

Attributes are variables that exist per instance of a class. They are where
the state of an object is stored. In Perl 6, all attributes are private.
They are typically declared using the C<has> declarator and the C<!> twigil.

    class Journey {
        has $!origin;
        has $!destination;
        has @!travelers;
        has $!notes;
    }

While there is no such thing as a public (or even protected) attribute,
there is a way to have accessor methods generated automatically: replace the
C<!> twigil with the C<.> twigil (the C<.> should remind you of a method
call).

    class Journey {
        has $.origin;
        has $.destination;
        has @!travelers;
        has $.notes;
    }

This defaults to providing a read-only accessor. In order to allow changes
to the attribute, add the L<is rw> trait:

    class Journey {
        has $.origin;
        has $.destination;
        has @!travelers;
        has $.notes is rw;
    }

Now, after a C<Journey> object is created, its C<.origin>, C<.destination>,
and C<.notes> will all be accessible from outside the class, but only
C<.notes> can be modified.

If an object is instantiated without certain attributes, such as origin or
destination, we may not get the desired result. To prevent this, provide
default values or make sure that an attribute is set on object creation
by marking an attribute with an L<is required> trait.

    class Journey {
        # error if origin is not provided
        has $.origin is required;
        # set the destination to Orlando as default (unless that is the origin!)
        has $.destination = self.origin eq 'Orlando' ?? 'Kampala' !! 'Orlando';
        has @!travelers;
        has $.notes is rw;
    }

Since classes inherit a default constructor from C<Mu> and we have requested
that some accessor methods are generated for us, our class is already
somewhat functional.

    =begin code :preamble<class Journey {};>
    # Create a new instance of the class.
    my $vacation = Journey.new(
        origin      => 'Sweden',
        destination => 'Switzerland',
        notes       => 'Pack hiking gear!'
    );

    # Use an accessor; this outputs Sweden.
    say $vacation.origin;

    # Use an rw accessor to change the value.
    $vacation.notes = 'Pack hiking gear and sunglasses!';
    =end code

Note that, although the default constructor can initialize read-only
attributes, it will only set attributes that have an accessor method.
That is, even if you pass C«travelers => ["Alex", "Betty"]» to the
default constructor, the attribute C<@!travelers> is not initialized.

=head2 Methods

Methods are declared with the C<method> keyword inside a class body.

    =begin code
    class Journey {
        has $.origin;
        has $.destination;
        has @!travelers;
        has $.notes is rw;

        method add-traveler($name) {
            if $name ne any(@!travelers) {
                push @!travelers, $name;
            }
            else {
                warn "$name is already going on the journey!";
            }
        }

        method describe() {
            "From $!origin to $!destination"
        }
    }
    =end code

A method can have a signature, just like a subroutine. Attributes can be
used in methods and can always be used with the C<!> twigil, even if they
are declared with the C<.> twigil. This is because the C<.> twigil
declares a C<!> twigil and generates an accessor method.

Looking at the code above,
there is a subtle but important difference between using C<$!origin>
and C<$.origin> in the method C<describe>.
C<$!origin> is an inexpensive and obvious lookup of the attribute.
C<$.origin> is a method call and thus may be overridden in a subclass.
Only use C<$.origin> if you want to allow overriding.

Unlike subroutines, additional named arguments will not produce compile time or
runtime errors. That allows chaining of methods via
L<Re-dispatching|/language/functions#Re-dispatching>.

You may write your own accessors to override any or all of the autogenerated ones.

    my $ⲧ = " " xx 4;
    class Journey {
        has $.origin;
        has $.destination;
        has @.travelers;
        has Str $.notes is rw;

        multi method notes() { "$!notes\n" };
        multi method notes( Str $note ) { $!notes ~= "$note\n$ⲧ" };

        method Str { "⤷ $!origin\n$ⲧ" ~ self.notes() ~ "$!destination ⤶\n" };
    }

    my $trip = Journey.new( :origin<Here>, :destination<There>,
                            travelers => <þor Freya> );

    $trip.notes("First steps");
    $trip.notes("Almost there");
    print $trip;

    # OUTPUT:
    #⤷ Here
    #       First steps
    #       Almost there
    #
    #There ⤶

The declared multi method C<notes> overrides the auto-generated
methods implicit in the declaration of C<$.notes>, using a different
signature for reading and writing.

Method names can be resolved at runtime with the C<.""> operator.

    class A { has $.b };
    my $name = 'b';
    A.new."$name"().say;
    # OUTPUT: «(Any)␤»

=head2 Class and Instance Methods

A method's signature can have an I<invocant> as its first parameter
followed by a colon, which allows for the method to refer to the object
it was called on.

    class Foo {
        method greet($me: $person) {
            say "Hi, I am $me.^name(), nice to meet you, $person";
        }
    }
    Foo.new.greet("Bob");    # OUTPUT: «Hi, I am Foo, nice to meet you, Bob␤»

Providing an invocant in the method signature also allows for defining
the method as either as a class method, or as an object method, through
the use of L<type constraints|/type/Signature#Type_Constraints>. The
C<::?CLASS> variable can be used to provide the class name at compile
time, combined with either C<:U> (for class methods) or C<:D> (for
instance methods).

    class Pizza {
        has $!radius = 42;
        has @.ingredients;

        # class method: construct from a list of ingredients
        method from-ingredients(::?CLASS:U $pizza: @ingredients) {
            $pizza.new( ingredients => @ingredients );
        }

        # instance method
        method get-radius(::?CLASS:D:) { $!radius }
    }
    my $p = Pizza.from-ingredients: <cheese pepperoni vegetables>;
    say $p.ingredients;     # OUTPUT: «[cheese pepperoni vegetables]␤»
    say $p.get-radius;      # OUTPUT: «42␤»
    say Pizza.get-radius;   # This will fail.
    CATCH { default { put .^name ~ ":\n" ~ .Str } };
    # OUTPUT: «X::Parameter::InvalidConcreteness:␤
    #          Invocant of method 'get-radius' must be
    #          an object instance of type 'Pizza',
    #          not a type object of type 'Pizza'.
    #          Did you forget a '.new'?»

A method can be both a class and object method by using the
L<multi|/syntax/multi> declarator:

    class C {
        multi method f(::?CLASS:U:) { say "class method"  }
        multi method f(::?CLASS:D:) { say "object method" }
    }
    C.f;       # OUTPUT: «class method␤»
    C.new.f;   # OUTPUT: «object method␤»

=head2 self

Inside a method, the term C<self> is available, which is bound to the
invocant.  C<self> can be used to call further methods on the invocant,
including constructors:

    class Box {
      has $.data;

      method make-new-box-from() {
          self.new: data => $!data;
      }
    }

C<self> can be used in class or instance methods as well, though beware
of trying to invoke one type of method from the other:

    class C {
        method g()            { 42     }
        method f(::?CLASS:U:) { self.g }
        method d(::?CLASS:D:) { self.f }
    }
    C.f;        # OUTPUT: «42␤»
    C.new.d;    # This will fail.
    CATCH { default { put .^name ~ ":\n" ~ .Str } };
    # OUTPUT: «X::Parameter::InvalidConcreteness:␤
    #          Invocant of method 'f' must be a type object of type 'C',
    #          not an object instance of type 'C'.  Did you forget a 'multi'?»

Within methods, C<$.origin> works the same as C<self.origin>, however
the colon-syntax for method arguments is only supported for method calls
using C<self>, not the shortcut.

Note that if the relevant methods C<bless>, C<CREATE> of L<Mu>
are not overloaded, C<self> will point to the type object in those methods.

On the other hand, C<BUILDALL> and the submethods C<BUILD> and C<TWEAK> are
called on instances, in different stages of initialization. In the latter two
submethods, submethods of the same name from subclasses have not yet run, so
you should not rely on potentially virtual method calls inside these methods.

=head2 Private Methods

Methods with an exclamation mark C<!> before the method name are not callable
from anywhere outside the defining class; such methods are private in the sense
that they are not visible from outside the class that declares them. Private
methods are invoked with an exclamation mark instead of a dot:

    method !do-something-private($x) {
        ...
    }
    method public($x) {
        if self.precondition {
            self!do-something-private(2 * $x)
        }
    }

Private methods are not inherited by subclasses.

=head2 Submethods

Submethods are public methods that are not inherited by subclasses. The name
stems from the fact that they are semantically similar to subroutines.

Submethods are useful for object construction and destruction tasks, as well
as for tasks that are so specific to a certain type that subtypes must
certainly override them.

For example, the L<default method new|/type/Mu#method_new> calls submethod
C<BUILD> on each class in an L<inheritance|#Inheritance> chain:

    =begin code
    class Point2D {
        has $.x;
        has $.y;

        submethod BUILD(:$!x, :$!y) {
            say "Initializing Point2D";
        }
    }

    class InvertiblePoint2D is Point2D {
        submethod BUILD() {
            say "Initializing InvertiblePoint2D";
        }
        method invert {
            self.new(x => - $.x, y => - $.y);
        }
    }

    say InvertiblePoint2D.new(x => 1, y => 2);
    # OUTPUT: «Initializing Point2D␤»
    # OUTPUT: «Initializing InvertiblePoint2D␤»
    # OUTPUT: «InvertiblePoint2D.new(x => 1, y => 2)␤»
    =end code

See also: L<#Object Construction>.

=head2 Inheritance

Classes can have I<parent classes>.

=for code :preamble<class Parent1 {}; class Parent2 {};>
class Child is Parent1 is Parent2 { }

If a method is called on the child class, and the child class does not
provide that method, the method of that name in one of the parent classes is
invoked instead, if it exists. The order in which parent classes are
consulted is called the I<method resolution order> (MRO). Perl 6 uses the
L<C3 method resolution order|https://en.wikipedia.org/wiki/C3_linearization>.
You can ask a type for its MRO through a call to its meta class:

    say List.^mro;      # ((List) (Cool) (Any) (Mu))

If a class does not specify a parent class, L<Any> is assumed by default.
All classes directly or indirectly derive from L<Mu>, the root of the type
hierarchy.

All calls to public methods are "virtual" in the C++ sense, which means that
the actual type of an object determines which method to call, not the
declared type:

    =begin code
    class Parent {
        method frob {
            say "the parent class frobs"
        }
    }

    class Child is Parent {
        method frob {
            say "the child's somewhat more fancy frob is called"
        }
    }

    my Parent $test;
    $test = Child.new;
    $test.frob;          # calls the frob method of Child rather than Parent
    # OUTPUT: «the child's somewhat more fancy frob is called␤»
    =end code

=head2 X<Object Construction|BUILDALL (method)>

Objects are generally created through method calls, either on the type
object or on another object of the same type.

Class L<Mu> provides a constructor method called L<new>, which takes named
arguments and uses them to initialize public attributes.

    class Point {
        has $.x;
        has $.y;
    }
    my $p = Point.new( x => 5, y => 2);
    #             ^^^ inherited from class Mu
    say "x: ", $p.x;
    say "y: ", $p.y;
    # OUTPUT: «x: 5␤»
    # OUTPUT: «y: 2␤»

C<Mu.new> calls method L<bless> on its invocant, passing all the named
arguments. C<bless> creates the new object and then calls method C<BUILDALL>
on it. C<BUILDALL> walks all subclasses in reverse method resolution order
(i.e. from L<Mu> to most derived classes) and in each class checks for the
existence of a method named C<BUILD>. If the method exists, the method is
called with all the named arguments from the C<new> method. If not, the public
attributes from this class are initialized from named arguments of the same
name. In either case, if neither C<BUILD> nor the default mechanism has
initialized the attribute, default values are applied.

X<|TWEAK>
After the C<BUILD> methods have been called, methods named C<TWEAK> are
called, if they exist, again with all the named arguments that were passed
to C<new>.

Due to the default behavior of C<BUILDALL> and C<BUILD>
submethods, named arguments to the constructor C<new> derived from C<Mu> can
correspond directly to public attributes of any of the classes in the method
resolution order, or to any named parameter of any C<BUILD> submethod.

This object construction scheme has several implications for customized
constructors. First, custom C<BUILD> methods should always be submethods,
otherwise they break attribute initialization in subclasses. Second,
C<BUILD> submethods can be used to run custom code at object construction
time. They can also be used for creating aliases for attribute
initialization:

    =begin code
    class EncodedBuffer {
        has $.enc;
        has $.data;

        submethod BUILD(:encoding(:$enc), :$data) {
            $!enc  :=  $enc;
            $!data := $data;
        }
    }
    my $b1 = EncodedBuffer.new( encoding => 'UTF-8', data => [64, 65] );
    my $b2 = EncodedBuffer.new( enc      => 'UTF-8', data => [64, 65] );
    #  both enc and encoding are allowed now
    =end code

Since passing arguments to a routine binds the arguments to the parameters,
a separate binding step is unnecessary if the attribute is used as a
parameter.  Hence the example above could also have been written as:

    =begin code :skip-test
    submethod BUILD(:encoding(:$!enc), :$!data) {
        # nothing to do here anymore, the signature binding
        # does all the work for us.
    }
    =end code

However, be careful when using this auto-binding of attributes
when the attribute may have special type requirements, such as an C<:$!id>
that must be a positive integer. Remember, default values will be assigned
unless you specifically take care of this attribute, and that
default value will be C<Any>, which would cause a type error.

The third implication is that if you want a constructor that accepts
positional arguments, you must write your own C<new> method:

    class Point {
        has $.x;
        has $.y;
        method new($x, $y) {
            self.bless(:$x, :$y);
        }
    }

However this is considered poor practice, because it makes correct
initialization of objects from subclasses harder.

Another thing to note is that the name C<new> is not special in Perl 6. It
is merely a common convention. You can call C<bless> from any method at all,
or use C<CREATE> to fiddle around with low-level workings.

Another pattern of hooking into object construction is
by writing your own method C<BUILDALL>. To make sure that
initialization of superclasses works fine, you
need to C<callsame> to invoke the parent classes C<BUILDALL>.

    =begin code
    class MyClass {
        method BUILDALL(|) {
            # initial things here

            callsame;   # call the parent classes (or default) BUILDALL

            # you can do final checks here.

            self # return the fully built object
        }
    }
    =end code

The C<TWEAK> method allows you to check things or modify attributes after
object construction:

    =begin code
    class RectangleWithCachedArea {
        has ($.x1, $.x2, $.y1, $.y2);
        has $.area;
        submethod TWEAK() {
            $!area = abs( ($!x2 - $!x1) * ( $!y2 - $!y1) );
        }
    }

    say RectangleWithCachedArea.new( x2 => 5, x1 => 1, y2 => 1, y1 => 0).area;
    # OUTPUT: «4␤»
    =end code

=head2 Object Cloning

The cloning is done using L<clone> method available on all objects, which
shallow-clones both public and private attributes. New values for I<public>
attributes can be supplied as named arguments.

    =begin code
    class Foo {
        has $.foo = 42;
        has $.bar = 100;
    }

    my $o1 = Foo.new;
    my $o2 = $o1.clone: :bar(5000);
    say $o1; # Foo.new(foo => 42, bar => 100)
    say $o2; # Foo.new(foo => 42, bar => 5000)
    =end code

See document for L<clone> for details on how non-scalar attributes get cloned,
as well as examples of implementing your own custom clone methods.

=head1 X<Roles|declarator,role>

Roles are in some ways similar to classes, in that they are a collection of
attributes and methods. They differ in that roles are also meant for
describing only parts of an object's behavior and in how roles are applied
to classes. Or to phrase it differently, classes are meant for managing
objects and roles are meant for managing behavior and code reuse.

    =begin code
    use MONKEY-SEE-NO-EVAL;
    role Serializable {
        method serialize() {
            self.perl; # very primitive serialization
        }
        method deserialize($buf) {
            EVAL $buf; # reverse operation to .perl
        }
    }

    class Point does Serializable {
        has $.x;
        has $.y;
    }
    my $p = Point.new(:x(1), :y(2));
    my $serialized = $p.serialize;
    my $clone-of-p = Point.deserialize($serialized);
    say $clone-of-p.x; # OUTPUT: «1␤»
    =end code

Roles are immutable as soon as the compiler parses the closing curly brace of
the role declaration.

=head2 Application of Role

Role application differs significantly from class inheritance. When a role
is applied to a class, the methods of that role are copied into the class.
If multiple roles are applied to the same class, conflicts (e.g.
attributes or non-multi methods of the same name) cause a compile-time error,
which can be solved by providing a method of the same name in the class.

This is much safer than multiple inheritance, where conflicts are never
detected by the compiler, but are instead resolved to the superclass
that appears earlier in the method resolution order, which might not
be what the programmer wanted.

For example, if you've discovered an efficient method to ride cows, and are
trying to market it as a new form of popular transportation, you might have
a class C<Bull>, for all the bulls you keep around the house, and a class
C<Automobile>, for things that you can drive.

    class Bull {
        has Bool $.castrated = False;
        method steer {
            # Turn your bull into a steer
            $!castrated = True;
            return self;
        }
    }
    class Automobile {
        has $.direction;
        method steer($!direction) { }
    }
    class Taurus is Bull is Automobile { }

    my $t = Taurus.new;
    say $t.steer;
    # OUTPUT: «Taurus.new(castrated => Bool::True, direction => Any)␤»

With this setup, your poor customers will find themselves unable to turn
their Taurus and you won't be able to make more of your product! In this
case, it may have been better to use roles:

    =begin code :skip-test
    role Bull-Like {
        has Bool $.castrated = False;
        method steer {
            # Turn your bull into a steer
            $!castrated = True;
            return self;
        }
    }
    role Steerable {
        has Real $.direction;
        method steer(Real $d = 0) {
            $!direction += $d;
        }
    }
    class Taurus does Bull-Like does Steerable { }
    =end code

This code will die with something like:

    =begin code :lang<text>
    ===SORRY!===
    Method 'steer' must be resolved by class Taurus because it exists in
    multiple roles (Steerable, Bull-Like)
    =end code

This check will save you a lot of headaches:

    =begin code :preamble<role Bull-Like{}; role Steerable{};>
    class Taurus does Bull-Like does Steerable {
        method steer($direction?) {
            self.Steerable::steer($direction)
        }
    }
    =end code

When a role is applied to a second role, the actual application is delayed
until the second role is applied to a class, at which point both roles are
applied to the class. Thus

    role R1 {
        # methods here
    }
    role R2 does R1 {
        # methods here
    }
    class C does R2 { }

produces the same class C<C> as

    role R1 {
        # methods here
    }
    role R2 {
        # methods here
    }
    class C does R1 does R2 { }

=head2 Stubs

When a role contains a L<stubbed|/routine/...> method,
a non-stubbed version of a method of the same name must be supplied
at the time the role is applied to a class. This allows you to
create roles that act as abstract interfaces.

    =begin code :skip-test
    role AbstractSerializable {
        method serialize() { ... }        # literal ... here marks the
                                          # method as a stub
    }

    # the following is a compile time error, for example
    #        Method 'serialize' must be implemented by Point because
    #        it's required by a role

    class APoint does AbstractSerializable {
        has $.x;
        has $.y;
    }

    # this works:
    class SPoint does AbstractSerializable {
        has $.x;
        has $.y;
        method serialize() { "p($.x, $.y)" }
    }
    =end code

The implementation of the stubbed method may also be provided by another
role.

=head2 Inheritance

Roles cannot inherit from classes, but they may cause any class which does
that role to inherit from another class. So if you write:

    =begin code
    role A is Exception { }
    class X::Ouch does A { }
    X::Ouch.^parents.say # OUTPUT: «((Exception))␤»
    =end code

then C<X::Ouch> will inherit directly from Exception, as we can see above
by listing its parents.

=head2 Pecking order

A method defined directly in a class will always override definitions from
applied roles or from inherited classes. If no such definition exists, methods
from roles override methods inherited from classes. This happens both when
said class was brought in by a role, and also when said class was inherited
directly.

    role M {
      method f { say "I am in role M" }
    }

    class A {
      method f { say "I am in class A" }
    }

    class B is A does M {
      method f { say "I am in class B" }
    }

    class C is A does M { }

    B.new.f; # OUTPUT «I am in class B␤»
    C.new.f; # OUTPUT «I am in role M␤»

Note that each candidate for a multi-method is its own method. In this case,
the above only applies if two such candidates have the same signature.
Otherwise, there is no conflict, and the candidate is just added to the
multi-method.

=head2 Automatic Role Punning

Any attempt to directly instantiate a role, as well as many other operations
on it, will automatically create an instance of a class with the same name as
the role, making it possible to transparently use a role as if it were a class.

    =begin code
    role Point {
        has $.x;
        has $.y;
        method abs { sqrt($.x * $.x + $.y * $.y) }
    }
    say Point.new(x => 6, y => 8).abs; # OUTPUT «10␤»
    =end code

We call this automatic creation of classes I<punning>, and the generated class
a I<pun>.

=head2 Parameterized Roles

X<|Parameterized Roles>

Roles can be parameterized, by giving them a signature in square brackets:

    =begin code
    role BinaryTree[::Type] {
        has BinaryTree[Type] $.left;
        has BinaryTree[Type] $.right;
        has Type $.node;

        method visit-preorder(&cb) {
            cb $.node;
            for $.left, $.right -> $branch {
                $branch.visit-preorder(&cb) if defined $branch;
            }
        }
        method visit-postorder(&cb) {
            for $.left, $.right -> $branch {
                $branch.visit-postorder(&cb) if defined $branch;
            }
            cb $.node;
        }
        method new-from-list(::?CLASS:U: *@el) {
            my $middle-index = @el.elems div 2;
            my @left         = @el[0 .. $middle-index - 1];
            my $middle       = @el[$middle-index];
            my @right        = @el[$middle-index + 1 .. *];
            self.new(
                node    => $middle,
                left    => @left  ?? self.new-from-list(@left)  !! self,
                right   => @right ?? self.new-from-list(@right) !! self,
            );
        }
    }

    my $t = BinaryTree[Int].new-from-list(4, 5, 6);
    $t.visit-preorder(&say);    # OUTPUT: «5␤4␤6␤»
    $t.visit-postorder(&say);   # OUTPUT: «4␤6␤5␤»
    =end code

Here the signature consists only of a type capture, but any signature will do:

    =begin code
    enum Severity <debug info warn error critical>;

    role Logging[$filehandle = $*ERR] {
        method log(Severity $sev, $message) {
            $filehandle.print("[{uc $sev}] $message\n");
        }
    }

    Logging[$*OUT].log(debug, 'here we go'); # OUTPUT: «[DEBUG] here we go␤»
    =end code

You can have multiple roles of the same name, but with different signatures;
the normal rules of multi dispatch apply for choosing multi candidates.

=head2 X<Mixins> of Roles

Roles can be mixed into objects. A role's given attributes and methods will be
added to the methods and attributes the object already has. Multiple mixins and
anonymous roles are supported.

    role R { method Str() {'hidden!'} };
    my $i = 2 but R;
    sub f(\bound){ put bound };
    f($i); # OUTPUT: «hidden!␤»

Note that the object got the role mixed in, not the object's class or the
container. Thus, @-sigiled containers will require binding to make the role
stick. Some operators will return a new value, which effectively strips
the mixin from the result.

Mixins can be used at any point in your object's life.

    # A counter for Table of Contents
    role TOC-Counter {
        has Int @!counters is default(0);
        method Str() { @!counters.join: '.' }
        method inc($level) {
            @!counters[$level - 1]++;
            @!counters.splice($level);
            self
        }
    }

    my Num $toc-counter = NaN;     # don't do math with Not A Number
    say $toc-counter;              # OUTPUT: «NaN␤»
    $toc-counter does TOC-Counter; # now we mix the role in
    $toc-counter.inc(1).inc(2).inc(2).inc(1).inc(2).inc(2).inc(3).inc(3);
    put $toc-counter / 1;          # OUTPUT: «NaN␤» (because that's numerical context)
    put $toc-counter;              # OUTPUT: «2.2.2␤» (put will call TOC-Counter::Str)

Roles can be anonymous.

    my %seen of Int is default(0 but role :: { method Str() {'NULL'} });
    say %seen<not-there>;          # OUTPUT: «NULL␤»
    say %seen<not-there>.defined;  # OUTPUT: «True␤» (0 may be False but is well defined)
    say Int.new(%seen<not-there>); # OUTPUT: «0␤»

=head1 Meta-Object Programming and Introspection

Perl 6 has a meta object system, which means that the behavior of objects,
classes, roles, grammars, enums, etc. are themselves controlled by other
objects; those objects are called I<meta objects>. Meta objects are, like
ordinary objects, instances of classes, in this case we call them I<meta
classes>.

For each object or class you can get the meta object by calling C<.HOW> on it.
Note that although this looks like a method call, it works more like a macro.

So, what can you do with the meta object? For one you can check if two
objects have the same meta class by comparing them for equality:

    say 1.HOW ===   2.HOW;      # OUTPUT: «True␤»
    say 1.HOW === Int.HOW;      # OUTPUT: «True␤»
    say 1.HOW === Num.HOW;      # OUTPUT: «False␤»

Perl 6 uses the word I<HOW>, Higher Order Workings, to refer to the meta
object system. Thus it should be no surprise that in Rakudo, the class name
of the meta class that controls class behavior is called
C<Perl6::Metamodel::ClassHOW>. For each class there is one instance of
C<Perl6::Metamodel::ClassHOW>.

But of course the meta model does much more for you. For example, it allows
you to introspect objects and classes. The calling convention for methods on
meta objects is to call the method on the meta object and pass in the object
of interest as first argument to the object. So to get the name of the class
of an object, you could write:

    my $object = 1;
    my $metaobject = 1.HOW;
    say $metaobject.name($object);      # OUTPUT: «Int␤»

    # or shorter:
    say 1.HOW.name(1);                  # OUTPUT: «Int␤»

(The motivation is that Perl 6 also wants to allow a more prototype-based
object system, where it's not necessary to create a new meta object for
every type).

There's a shortcut to keep from using the same object twice:

    say 1.^name;                        # OUTPUT: «Int␤»
    # same as
    say 1.HOW.name(1);                  # OUTPUT: «Int␤»

See L<Metamodel::ClassHOW|/type/Metamodel::ClassHOW> for documentation on
the meta class of C<class> and also the L<general documentation on the meta
object protocol|/language/mop>.

=end pod

# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6
